package com.bdqn.demo;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 示例6：通过反射调用类的方法
 *
 * @author LILIBO
 * @since 2022-09-15
 */
public class Demo06 {

    public static void main(String[] args) {
        // 通过Class.forName()方法获取Class
        Class clazz = null;
        try {
            clazz = Class.forName("com.bdqn.pojo.Student");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        // 通过反射调用类的方法
        try {
            System.out.println("通过反射调用对象的方法: ");
            // 通过反射创建类的实例（对象） newInstance()
            Object obj01 = clazz.newInstance();
            System.out.println(obj01);

            System.out.println("通过构造函数创建对象: ");
            // 获取某个构造函数
            Constructor constructor = clazz.getDeclaredConstructor(String.class, int.class, String.class);
            // 上帝视角，跨过访问权限调用（原来private的方法此处已超出访问限制，但是通过setAccessible(true)可以设定为可访问！）
            constructor.setAccessible(true);
            // 通过构造函数创建对象（传递构造函数需要的参数）
            Object obj02 = constructor.newInstance("张三", 18, "湖南郴州");
            // 获取类的方法（获取参数为String类型的setName方法，返回的是Method对象）
            Method setName = clazz.getDeclaredMethod("setName", String.class);
            // 上帝视角，跨过访问权限调用
            setName.setAccessible(true);
            // 通过反射执行类的方法（第一个必填参数为执行该方法的对象，后续可选参数为执行该方法传递的参数列表，返回的对象为方法执行后的返回结果）
            Object methodReturn = setName.invoke(obj02, "老王");
            System.out.println(methodReturn); // 输出通过反射执行方法后的返回结果，如果没有返回结果返回null
            // 获得无参的public的getName方法
            Method getName = clazz.getMethod("getName");
            // 使用obj02对象调用getName方法并打印返回结果
            System.out.println(getName.invoke(obj02));
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

}
